﻿using System;
using System.Collections.Generic;


namespace ExtensibleEventViewer.Core.Primitives
{
	/// <summary>
	/// Represents single event log entity
	/// </summary>
	[Serializable]
	public class EventLogEntity
	{
		private readonly Func<IEnumerable<EventLogRecord>> _getRecords;
		private readonly Func<bool> _clearRecords;
		private readonly List<EventLogRecord> _eventRecords = new List<EventLogRecord>();


		public EventLogEntity()
		{
		}

		/// <summary>
		/// Initializes EventLogEntity instance
		/// </summary>
		/// <param name="name">EventLogEntity name</param>
		/// <param name="computerName">Computer name where EventLogEntity located</param>
		/// <param name="records">List of records related to current event log</param>
		/// <param name="clearRecords">Delegate which will be invoked to clear all records</param>
		public EventLogEntity(
			string name, 
			string computerName, 
			IEnumerable<EventLogRecord> records,
			Func<bool> clearRecords)
		{
			Name = name;
			ComputerName = computerName;

			_eventRecords.AddRange(records);
			_clearRecords = clearRecords;
		}

		/// <summary>
		/// Initializes EventLogEntity instance
		/// </summary>
		/// <param name="name">EventLogEntity name</param>
		/// <param name="computerName">Computer name where EventLogEntity located</param>
		/// <param name="getRecords">Delegate which will be invoked to get event log records associated with current event log</param>
		/// <param name="clearRecords">Delegate which will be invoked to clear all records</param>
		public EventLogEntity(
			string name, 
			string computerName, 
			Func<IEnumerable<EventLogRecord>> getRecords,
			Func<bool> clearRecords)
		{
			Name = name;
			ComputerName = computerName;

			_getRecords = getRecords;
			_clearRecords = clearRecords;
		}

		/// <summary>
		/// Gets name of the <see cref="EventLogEntity"/>
		/// </summary>
		public string Name
		{
			get; 
			set;
		}

		/// <summary>
		/// Gets computer name where current <see cref="EventLogEntity"/> located
		/// </summary>
		public string ComputerName
		{
			get; 
			set;
		}

		/// <summary>
		/// Gets list of records related to current <see cref="EventLogEntity"/> instance
		/// </summary>
		public IEnumerable<EventLogRecord> GetEventRecords()
		{
			if (_getRecords != null)
			{
				return (IEnumerable<EventLogRecord>)_getRecords.DynamicInvoke();
			}

			return _eventRecords;
		}

		public bool Clear()
		{
			if(_clearRecords != null)
			{
				return _clearRecords();
			}

			return false;
		}

		/// <summary>
		/// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
		/// </summary>
		/// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
		/// <returns>
		/// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
		/// </returns>
		/// <exception cref="T:System.NullReferenceException">
		/// The <paramref name="obj"/> parameter is null.
		/// </exception>
		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return false;
			}

			if (obj is EventLogEntity)
			{
				EventLogEntity logEntity = (EventLogEntity) obj;

				if (string.Equals(logEntity.Name, Name))
				{
					if (string.Equals(logEntity.ComputerName, ComputerName))
					{
						return true;
					}
				}
			}

			return false;
		}

		/// <summary>
		/// Serves as a hash function for a particular type.
		/// </summary>
		/// <returns>
		/// A hash code for the current <see cref="T:System.Object"/>.
		/// </returns>
		public override int GetHashCode()
		{
			string completeName = Name + ComputerName;

			return completeName.GetHashCode();
		}

		/// <summary>
		/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
		/// </returns>
		public override string ToString()
		{
			return Name;
		}
	}
}
